/*
 * This file is part of Smart Route for S60 3rd Edition terminals
 * 
 * Copyright (C) 2006  Harri Salminen

 * This program free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 *(at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
 */

#include "SmartRouteLocator.h"
#include "SmartRouteDataStore.h"
#include "SmartRouteEngine.h"

CSmartRouteLocator* CSmartRouteLocator::NewL(CSmartRouteEngine& aEngine)
	{
	CSmartRouteLocator* self = new (ELeave) CSmartRouteLocator(aEngine);
	CleanupStack::PushL(self);
	self->ConstructL();
	CleanupStack::Pop(); 
	return self; 
	}

CSmartRouteLocator::CSmartRouteLocator(CSmartRouteEngine& aEngine) : 
	CActive(EPriorityStandard),
	iEngine(aEngine),
	iState(EIdle)
	{
	}

void CSmartRouteLocator::ConstructL() 
	{
	CActiveScheduler::Add(this);				// Add to scheduler
	 
	User::LeaveIfError(iPositionServer.Connect());
	User::LeaveIfError(iPositioner.Open(iPositionServer));
	
	iRequestor = CRequestor::NewL(CRequestor::ERequestorService,
		CRequestor::EFormatApplication,KAppName);
	iRequestorStack.Append(iRequestor);
	User::LeaveIfError(iPositioner.SetRequestor(iRequestorStack));
	}

CSmartRouteLocator::~CSmartRouteLocator()
	{
	Cancel();
	iRequestorStack.Reset();
	iPositioner.Close();
	iPositionServer.Close();
	delete iRequestor;
	}

void CSmartRouteLocator::DoCancel()
	{
	iPositioner.CancelRequest(EPositionerNotifyPositionUpdate);
	iState = EIdle;
	}

void CSmartRouteLocator::StartL(TTimeIntervalSeconds aFrequency)
	{
	if(iState != ERunning)
		{	
		TPositionUpdateOptions updateOptions(aFrequency.Int() * KSecond); //Frequency must be microseconds
		User::LeaveIfError(iPositioner.SetUpdateOptions(updateOptions));	
		iState = ERunning;
		if(!IsActive())
		    {
		    iPositioner.NotifyPositionUpdate(iPositionInfo, iStatus);	
		    SetActive();
		    }
		}
	}
	
void CSmartRouteLocator::Pause()
	{
	iState = EPaused;
	}

void CSmartRouteLocator::RunL()
	{
	if(iStatus.Int() == KErrNone)
		{
		TCourse course; 
		iPositionInfo.GetCourse(course);
		
		if(iMaxSpeed<course.Speed())
		    iMaxSpeed=course.Speed();
		
		TReal32 distance;
		TPosition currPosition, oldPosition;
		iPositionInfo.GetPosition(currPosition);
		iPreviousPositionInfo.GetPosition(oldPosition);
		if(currPosition.Distance(oldPosition, distance) == KErrNone)
			iDistance+=distance;
			
		iPreviousPositionInfo = iPositionInfo;
		
		TRoutePoint routePoint; 
		routePoint.iAltitude = currPosition.Altitude();
		routePoint.iLatitude = currPosition.Latitude();
		routePoint.iLongitude= currPosition.Longitude();
		iEngine.AddRoutePointL(routePoint);
		}
	
	//Pause might have been issued
	if(iState == ERunning)
		{
		iPositioner.NotifyPositionUpdate(iPositionInfo, iStatus);				
		SetActive();
		}
	}
	
TReal32 CSmartRouteLocator::Distance() const
	{
	return iDistance;
	}
	
TReal32 CSmartRouteLocator::MaxSpeed() const
	{
	return iMaxSpeed;
	}
